package com.jh.paymentchannel.pojo;

import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.google.common.base.MoreObjects;
import com.jh.paymentchannel.payment.OrderType;
import com.jh.paymentchannel.payment.PaymentUtils;
import com.jh.paymentchannel.payment.TradeStatus;
import com.jh.paymentchannel.payment.alipay.AlipayPayResult;
import com.jh.paymentchannel.payment.wechat.WechatPayResult;
import javax.persistence.Transient;

import javax.persistence.*;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;

import static io.jsonwebtoken.lang.Strings.hasText;

/**
 * @author Yichuan
 * @version 1.0
 */
@Entity
@Table(name="t_payment_order")
public class PaymentOrder implements Serializable {

    private static final long serialVersionUID = -5654046976981813083L;

    public static PaymentOrder newOrder(String appId, Long userId, String shopId, String shopName, String subMchId,
                                        BigDecimal totalFee, OrderType orderType) {
        PaymentOrder order = new PaymentOrder();
        order.setAppId(appId);
        order.setShopId(shopId);
        order.setUserId(userId);
        order.setShopName(shopName);
        order.setSubMchId(subMchId);
        String outTradeNo = PaymentUtils.getOrderIdByUUId(orderType.getCode());
        order.setOutTradeNo(outTradeNo);
        order.setTotalFee(totalFee);
        // 购买商品信息(待查)
        order.setBody("线下消费");
        order.setDetail("线下消费");
        order.setOrderType(orderType);
        order.setTradeStatus(TradeStatus.WAIT_BUYER_PAY);
        Date currDate = new Date();
        order.setUpdateTime(currDate);
        order.setCreateTime(currDate);
        return order;
    }

    @Id
    @Column(name="order_id")
    private long orderId;

    /** 应用id */
    @Column(name="appid")
    private String appId;

    /** 用户id */
    @Column(name = "user_id")
    private Long userId;

    /** 商户id **/
    @Column(name="shop_id")
    private String shopId;

    /** 商户名 **/
    @Column(name="shop_name")
    private String shopName;

    /** 设备号 ***/
    @Column(name="device_info")
    private String deviceInfo;

    /** 子商户号 */
    @Column(name = "sub_mch_id")
    private String subMchId;

    /** 随机字符串 */
    @Column(name="nonce_str")
    private String nonceStr;

    /** 签名 */
    @Column(name="sign")
    private String sign;

    /** 签名类型 */
    @Column(name="sign_type")
    private String signType;

    /**总金额*/
    @Column(name="total_fee")
    private BigDecimal totalFee;

    /** 商品描述 */
    @Column(name="body")
    private String body;

    /** 商品详情 */
    @Column(name="detail")
    private String detail;

    /** 商品订单号 */
    @Column(name="out_trade_no")
    private String outTradeNo;

    /** 交易号(上游返回) */
    @Column(name="trade_no")
    private String tradeNo;

    /** 订单类型 */
    @Enumerated(EnumType.STRING)
    @Column(name="order_type")
    private OrderType orderType;

    /** 交易状态 */
    @Enumerated(EnumType.STRING)
    @Column(name="trade_status")
    private TradeStatus tradeStatus;

    /** 付款银行 */
    @Column(name="trade_bank")
    private String tradeBank;

    /** 货币种类 */
    @Column(name="fee_type")
    private String feeType;

    /** 预支付标识 */
    @Column(name="prepay_id")
    private String prepayId;

    /** 终端IP */
    @Column(name="spbill_create_ip")
    private String spbillCreateIp;

    /** 订单优惠标记 */
    @Column(name="goods_tag")
    private String goodsTag;

    /** 扩展信息 */
    @Column(name="extra_info")
    private String extraInfo;

    /** 商家数据包 */
    @Column(name="attach")
    private String attach;

    /** 返回状态码 */
    @Column(name="return_code")
    private String returnCode;

    /** 返回信息 */
    @Column(name="return_msg")
    private String returnMsg;

    /** 业务结果 */
    @Column(name="result_code")
    private String resultCode;

    @Column(name="update_time")
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;

    @Column(name="create_time")
    @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
    private Date createTime;

    /** 返佣金额 */
    @Transient
    private BigDecimal rebateAmount = new BigDecimal("0.00");

    /** 5：个人，6：代理 */
    @Transient
    private long roleId;

    public BigDecimal getRebateAmount() {
        return rebateAmount;
    }

    public void setRebateAmount(BigDecimal rebateAmount) {
        this.rebateAmount = rebateAmount;
    }

    public long getRoleId() {
        return roleId;
    }

    public void setRoleId(long roleId) {
        this.roleId = roleId;
    }

    public PaymentOrder() {
        super();
    }

    public long getOrderId() {
        return orderId;
    }

    public void setOrderId(long orderId) {
        this.orderId = orderId;
    }

    public String getAppId() {
        return appId;
    }

    public void setAppId(String appId) {
        this.appId = appId;
    }

    public Long getUserId() {
        return userId;
    }

    public void setUserId(Long userId) {
        this.userId = userId;
    }

    public String getShopId() {
        return shopId;
    }

    public void setShopId(String shopId) {
        this.shopId = shopId;
    }

    public String getShopName() {
        return shopName;
    }

    public void setShopName(String shopName) {
        this.shopName = shopName;
    }

    public String getDeviceInfo() {
        return deviceInfo;
    }

    public void setDeviceInfo(String deviceInfo) {
        this.deviceInfo = deviceInfo;
    }

    public String getSubMchId() {
        return subMchId;
    }

    public void setSubMchId(String subMchId) {
        this.subMchId = subMchId;
    }

    public String getNonceStr() {
        return nonceStr;
    }

    public void setNonceStr(String nonceStr) {
        this.nonceStr = nonceStr;
    }

    public String getSign() {
        return sign;
    }

    public void setSign(String sign) {
        this.sign = sign;
    }

    public String getSignType() {
        return signType;
    }

    public void setSignType(String signType) {
        this.signType = signType;
    }

    public BigDecimal getTotalFee() {
        return totalFee;
    }

    public void setTotalFee(BigDecimal totalFee) {
        this.totalFee = totalFee;
    }

    public String getBody() {
        return body;
    }

    public void setBody(String body) {
        this.body = body;
    }

    public String getDetail() {
        return detail;
    }

    public void setDetail(String detail) {
        this.detail = detail;
    }

    public String getOutTradeNo() {
        return outTradeNo;
    }

    public void setOutTradeNo(String outTradeNo) {
        this.outTradeNo = outTradeNo;
    }

    public String getTradeNo() {
        return tradeNo;
    }

    public void setTradeNo(String tradeNo) {
        this.tradeNo = tradeNo;
    }

    public OrderType getOrderType() {
        return orderType;
    }

    public void setOrderType(OrderType orderType) {
        this.orderType = orderType;
    }

    public TradeStatus getTradeStatus() {
        return tradeStatus;
    }

    public void setTradeStatus(TradeStatus tradeStatus) {
        this.tradeStatus = tradeStatus;
    }

    public String getTradeBank() {
        return tradeBank;
    }

    public void setTradeBank(String tradeBank) {
        this.tradeBank = tradeBank;
    }

    public String getFeeType() {
        return feeType;
    }

    public void setFeeType(String feeType) {
        this.feeType = feeType;
    }

    public String getPrepayId() {
        return prepayId;
    }

    public void setPrepayId(String prepayId) {
        this.prepayId = prepayId;
    }

    public String getSpbillCreateIp() {
        return spbillCreateIp;
    }

    public void setSpbillCreateIp(String spbillCreateIp) {
        this.spbillCreateIp = spbillCreateIp;
    }

    public String getGoodsTag() {
        return goodsTag;
    }

    public void setGoodsTag(String goodsTag) {
        this.goodsTag = goodsTag;
    }

    public String getExtraInfo() {
        return extraInfo;
    }

    public void setExtraInfo(String extraInfo) {
        this.extraInfo = extraInfo;
    }

    public String getAttach() {
        return attach;
    }

    public void setAttach(String attach) {
        this.attach = attach;
    }

    public String getReturnCode() {
        return returnCode;
    }

    public void setReturnCode(String returnCode) {
        this.returnCode = returnCode;
    }

    public String getReturnMsg() {
        return returnMsg;
    }

    public void setReturnMsg(String returnMsg) {
        this.returnMsg = returnMsg;
    }

    public String getResultCode() {
        return resultCode;
    }

    public void setResultCode(String resultCode) {
        this.resultCode = resultCode;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    public Date getCreateTime() {
        return createTime;
    }

    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof PaymentOrder)) return false;
        PaymentOrder that = (PaymentOrder) o;
        return getOrderId() == that.getOrderId() &&
                Objects.equals(getAppId(), that.getAppId()) &&
                Objects.equals(getUserId(), that.getUserId()) &&
                Objects.equals(getShopId(), that.getShopId()) &&
                Objects.equals(getShopName(), that.getShopName()) &&
                Objects.equals(getDeviceInfo(), that.getDeviceInfo()) &&
                Objects.equals(getSubMchId(), that.getSubMchId()) &&
                Objects.equals(getNonceStr(), that.getNonceStr()) &&
                Objects.equals(getSign(), that.getSign()) &&
                Objects.equals(getSignType(), that.getSignType()) &&
                Objects.equals(getTotalFee(), that.getTotalFee()) &&
                Objects.equals(getBody(), that.getBody()) &&
                Objects.equals(getDetail(), that.getDetail()) &&
                Objects.equals(getOutTradeNo(), that.getOutTradeNo()) &&
                Objects.equals(getTradeNo(), that.getTradeNo()) &&
                getOrderType() == that.getOrderType() &&
                getTradeStatus() == that.getTradeStatus() &&
                Objects.equals(getTradeBank(), that.getTradeBank()) &&
                Objects.equals(getFeeType(), that.getFeeType()) &&
                Objects.equals(getPrepayId(), that.getPrepayId()) &&
                Objects.equals(getSpbillCreateIp(), that.getSpbillCreateIp()) &&
                Objects.equals(getGoodsTag(), that.getGoodsTag()) &&
                Objects.equals(getExtraInfo(), that.getExtraInfo()) &&
                Objects.equals(getAttach(), that.getAttach()) &&
                Objects.equals(getReturnCode(), that.getReturnCode()) &&
                Objects.equals(getReturnMsg(), that.getReturnMsg()) &&
                Objects.equals(getResultCode(), that.getResultCode()) &&
                Objects.equals(getUpdateTime(), that.getUpdateTime()) &&
                Objects.equals(getCreateTime(), that.getCreateTime());
    }

    @Override
    public int hashCode() {
        return Objects.hash(getOrderId(), getAppId(), getUserId(), getShopId(), getShopName(), getDeviceInfo(), getSubMchId(), getNonceStr(),
                getSign(), getSignType(), getTotalFee(), getBody(), getDetail(), getOutTradeNo(),
                getTradeNo(), getOrderType(), getTradeStatus(), getTradeBank(), getFeeType(), getPrepayId(),
                getSpbillCreateIp(), getGoodsTag(), getExtraInfo(), getAttach(),
                getReturnCode(), getReturnMsg(), getResultCode(), getUpdateTime(), getCreateTime());
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("orderId", orderId)
                .add("appId", appId)
                .add("userId", userId)
                .add("shopId", shopId)
                .add("shopName", shopName)
                .add("deviceInfo", deviceInfo)
                .add("subMchId", subMchId)
                .add("nonceStr", nonceStr)
                .add("sign", sign)
                .add("signType", signType)
                .add("totalFee", totalFee)
                .add("body", body)
                .add("detail", detail)
                .add("outTradeNo", outTradeNo)
                .add("tradeNo", tradeNo)
                .add("orderType", orderType)
                .add("tradeStatus", tradeStatus)
                .add("tradeBank", tradeBank)
                .add("feeType", feeType)
                .add("prepayId", prepayId)
                .add("spbillCreateIp", spbillCreateIp)
                .add("goodsTag", goodsTag)
                .add("extraInfo", extraInfo)
                .add("attach", attach)
                .add("returnCode", returnCode)
                .add("returnMsg", returnMsg)
                .add("resultCode", resultCode)
                .add("updateTime", updateTime)
                .add("createTime", createTime)
                .toString();
    }

    public AlipayTradeWapPayModel alipayTradeWapPayModel() {
        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        model.setOutTradeNo(getOutTradeNo());
        model.setSubject(getDetail());
        model.setTotalAmount(getTotalFee().toPlainString());
        model.setBody(getBody());
        model.setTimeoutExpress("30m");
        model.setProductCode("QUICK_WAP_PAY");
        return model;
    }

    public PaymentOrder alipay(AlipayPayResult payResult) {
        setTradeStatus(payResult.getTradeStatus());
        if (hasText(payResult.getSign())) {
            setSign(payResult.getSign());
        }
        if (hasText(payResult.getSignType())) {
            setSignType(payResult.getSignType());
        }
        if (hasText(payResult.getTradeNo())) {
            setTradeNo(payResult.getTradeNo());
        }
        return this;
    }

    public PaymentOrder alipayQueryResponse(AlipayTradeQueryResponse queryResponse, TradeStatus tradeStatus) {
        setTradeNo(queryResponse.getTradeNo());
        setTotalFee(new BigDecimal(queryResponse.getTotalAmount()));
        setTradeStatus(tradeStatus);
        setUpdateTime(new Date());
        return this;
    }

    public PaymentOrder wechat(WechatPayResult payResult) {
        setTradeStatus(payResult.getStatus());
        if (hasText(payResult.getTradeNo())) {
            setTradeNo(payResult.getTradeNo());
        }
        setReturnCode(payResult.getReturnCode());
        if (hasText(payResult.getResultCode())) {
            setResultCode(payResult.getResultCode());
        }
        if (hasText(payResult.getReturnMsg())) {
            setReturnMsg(payResult.getReturnMsg());
        }
        if (hasText(payResult.getResultCode())) {
            setResultCode(payResult.getResultCode());
        }
        if (hasText(payResult.getDeviceInfo())) {
            setDeviceInfo(payResult.getDeviceInfo());
        }
        if (hasText(payResult.getBankType())) {
            setTradeBank(payResult.getBankType());
        }
        if (hasText(payResult.getSign())) {
            setSign(payResult.getSign());
        }
        if (hasText(payResult.getFeeType())) {
            setFeeType(payResult.getFeeType());
        }
        if (hasText(payResult.getNonceStr())) {
            setNonceStr(payResult.getNonceStr());
        }
        setUpdateTime(new Date());
        return this;
    }
}
